package com.zx.练习题._2020面试题;

import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;

/*
【Boos直聘】 表2个：下表是1对多
    t_order  微信分享砍价表
        微信分享砍价订单id -- 唯一
        发起人账户id
        商品id
        发起时间
        总金额
        砍价的总金额
        砍价是否完成的状态
        分享的连接
    t_order_operation 砍价记录表
        id
        order_id        uidx_1 唯一索引左边
        砍价人的账户       uidx_1 唯一索引右边
        砍价金额
        砍价时间
 */
public class 设计微信砍价的功能 {


    public interface OrderService {

        /**
         * 发起分享
         *
         * @param orderId 用户打开分享界面时已经创建好一个id
         * @param userId
         * @param goodsId
         */
        void apply(Long orderId, String userId, String goodsId);

        /**
         * 砍价
         */
        void down(Long orderId, String userId);


    }

    public class OrderServiceImpl implements OrderService {

        // 这个过程不加锁，使用orderId 作为实现幂等性的唯一约束
        @Override
        public void apply(Long orderId, String userId, String goodsId) {
            // userId, goodsId 查询用户已经分享砍价过这个商品
            boolean check = this.checkApply(orderId, userId, goodsId);
            if (!check) {
                throw new RuntimeException("不能分享已经分享过的商品");
            }
            Order order = new Order();
            order.setOrderId(orderId);
            order.setUserId(userId);
            order.setGoodsId(goodsId);
            order.setCreateTime(new Date());
            order.setAmount(this.getAmount(goodsId));// 查询价格
            order.setAmountDown(BigDecimal.ZERO);
            order.setUrl("http:///11asgdasgd");// 生成URL
            order.setState(0);

            //保存，使用insert ignore 不报错，返回插入的数据条数
            if (this.save(order) == 1) {
                throw new RuntimeException("订单已经存在不能重新。。。");
            }
        }

        @Override
        public void down(Long orderId, String userId) {
            if (this.checkDown(orderId, userId)) {
                throw new RuntimeException("已经砍过价了");
            }
            // 分布式锁
            String key = "order:down:" + orderId;
            try {
                if (lock(key)) {
                    // 1. 计算砍多少钱
                    // 2. 保存OrderOperation
                    // 3. 判断是否修改order状态
                } else {
                    throw new RuntimeException("业务繁忙请稍后再试~");
                }
            } catch (Exception e) {

            } finally {
                this.unlock(key);
            }

        }

        /**
         * 多重校验
         *
         * @param orderId
         * @param userId
         * @param goodsId
         * @return
         */
        boolean checkApply(Long orderId, String userId, String goodsId) {
            return true;
        }

        boolean checkDown(Long orderId, String userId) {
            return true;
        }

        BigDecimal getAmount(String goodsId) {
            return BigDecimal.TEN;
        }

        int save(Order order) {
            return 1;
        }

        boolean lock(String key) {
            return true;
        }

        boolean unlock(String key) {
            return true;
        }

    }

    @Data
    public class Order {

        private Long orderId;
        private String userId;
        private String goodsId;
        private Date createTime;
        private BigDecimal amount;
        private BigDecimal amountDown;
        private String url;
        private int state;
    }

    @Data
    public class OrderOperation {

        private Long id;
        private Long orderId;
        private String userId;
        private Date createTime;
        private BigDecimal amountDown;
    }
}
